#include "threadPool.h"
void *threadFunc(void *arg){
    threadPool_t *pthreadPool = (threadPool_t *)arg;
    
    while(1){
        int netfd;
        pthread_mutex_lock(&pthreadPool->mutex);

        while(pthreadPool->taskQueue.queueSize == 0 && pthreadPool->exitFlag == 0){
            pthread_cond_wait(&pthreadPool->cond,&pthreadPool->mutex);
        }
        if(pthreadPool->exitFlag == 1){
            printf("A worker is going to exit!\n");
            pthread_mutex_unlock(&pthreadPool->mutex);
            pthread_exit(NULL);
        }
        netfd = pthreadPool->taskQueue.pFront->netfd;
        deQueue(&pthreadPool->taskQueue);
        pthread_mutex_unlock(&pthreadPool->mutex);
        printf("i am niger! i got netfd = %d\n",netfd);
        while(1){
            loginInfo_t loginInfo,resp_client;

            dirStack_t dirStack;
            char *absBuf="/home/zhb/ ..../";
            char sendBuf[4096]={0};
            char new_salt[21]={0};
            /* int rd; */
            int op,ret;
            ret = recv(netfd,&loginInfo,sizeof(loginInfo),MSG_WAITALL); // 接收传递过来的cmd，data
            if(ret <= 0){
                // 加入销毁dir栈操作
                destroyDirStack(&dirStack);   
                close(netfd);
                break;
            }

            int goal = loginInfo.cmd; // 将操作数取出赋值给goal
            char *bufRead = loginInfo.data; // 将客户端传进来的字符串取出

            // 统一声明 MySQL 连接指针
            MYSQL *conn = NULL;
            int own_conn = 0;
            
            int id = get_uid_fileSystem(loginInfo.usrName,conn);
            initDirStack(&dirStack,id);
            // 只要有 mysql_pool 就尝试获取连接（部分命令不用也无妨）
            if (pthreadPool->mysql_pool && mysql_pool_get(pthreadPool->mysql_pool, &conn) == 0 && conn != NULL) {
                own_conn = 1;
            }

            switch(goal){
            case 0:
                // cd
                ret = cdFunc(&dirStack,bufRead,conn,loginInfo.usrName);
                LOG_CHECK(ret,"cdFunc");
                if(ret == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:cd");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                break;
            case 1:
                // ls
                ret = lsFunc(conn,&dirStack,loginInfo.usrName,bufRead,sendBuf);
                LOG_CHECK(ret,"lsFunc");
                if(ret == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:ls");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                break;
            case 2:
                bzero(sendBuf,sizeof(sendBuf));
                ret = pwdFunc(&dirStack,sendBuf,conn,loginInfo.usrName);
                LOG_CHECK(ret,"pwdFunc");
                if(ret == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:pwd");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                sleep(1);
                break;
            case 3:
                // mkdir
                ret = mkdirFunc(&dirStack,bufRead,conn,loginInfo.usrName);
                LOG_CHECK(ret,"mkdirFunc");
                if(ret == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:mkdir");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                break;
            case 4:
                // rmdir
                bzero(sendBuf,sizeof(sendBuf));
                ret = rmdirFunc(&dirStack,bufRead,sendBuf,conn,loginInfo.usrName);
                LOG_CHECK(ret,"rmdirFunc");
                if(ret == -1){
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                break;
            case 5:
                // puts 传输
                op = putsFiletoClient(netfd,bufRead,absBuf,loginInfo.usrName,conn);
                if(op == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:getsFile");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                LOG_CHECK(op,"getsFile");
                /* break; */
                break;
            case 6:
                // gets 接收
                op = getsFilefromClient(netfd,bufRead,absBuf,loginInfo.usrName,conn);
                if(op == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:putsFile");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                LOG_CHECK(op,"putsFile");
                break;
            case 7:
                op = removeFile(netfd,bufRead,absBuf,loginInfo.usrName,conn);
                if(op == -1){
                    bzero(sendBuf,sizeof(sendBuf));
                    strcpy(sendBuf,"[ERROR]:removeFile");
                    send(netfd,sendBuf,strlen(sendBuf),MSG_NOSIGNAL);
                }
                LOG_CHECK(op,"removeFile");
                break;
            case 8:
                // 判断用户是不是存在
                if(conn){
                    ret = user_exist(loginInfo.usrName,conn);
                    if (ret == 0) {
                        resp_client.cmd = 1;
                    } else {
                        resp_client.cmd = 0;
                    }
                }
                send(netfd,&resp_client,sizeof(resp_client), MSG_NOSIGNAL);
                break;
            case 9:
                if(conn){
                    bzero(new_salt,sizeof(new_salt));
                    ret = getsalt(loginInfo.usrName,new_salt,conn);
                    if (ret == 0) {
                        strcpy(resp_client.salt,new_salt);
                        resp_client.cmd = 0;
                    } else {
                        strcpy(resp_client.salt,"without any salt");
                        resp_client.cmd = -1;
                    }
                }
                send(netfd,&resp_client,sizeof(resp_client), MSG_NOSIGNAL);
                break;
            case 10:
                if(conn){
                    bzero(new_salt,sizeof(new_salt));
                    ret = make_salt(loginInfo.usrName,new_salt,conn);
                    if (ret == 0) {
                        op = user_insert(loginInfo.usrName,new_salt,conn); 
                        ERROR_CHECK(op,-1,"user_insert");
                        resp_client.cmd = 0;
                    } else {
                        resp_client.cmd = -1;
                    }
                }
                send(netfd,&resp_client,sizeof(resp_client), MSG_NOSIGNAL);
                break;
            case 11:
                if(conn) {
                    // 登录逻辑
                    ret = user_login(loginInfo.usrName,loginInfo.ciphertxt,conn);
                    if (ret == 0) {
                        /* snprintf(sendBuf, sizeof(sendBuf), "login ok"); */
                        resp_client.cmd = 0;
                    } else {
                        /* snprintf(sendBuf, sizeof(sendBuf), "[ERROR]:login failed"); */
                        resp_client.cmd = -1;
                    }
                }
                /* } else { */
                /*     strcpy(sendBuf, "[ERROR]:No free MySQL connection for login"); */
                /* } */
                send(netfd,&resp_client,sizeof(resp_client), MSG_NOSIGNAL);
                break;
            case 12:
                if(conn) {
                    // 注册逻辑
                    ret = user_regist(loginInfo.usrName,loginInfo.salt,conn);
                    /* snprintf(sendBuf, sizeof(sendBuf), "register ok (stub)"); */
                    if (ret == 0) {
                        resp_client.cmd = 0;
                        op = user_file_insert(loginInfo.usrName,conn);
                        ERROR_CHECK(op,-1,"user_file_insert");
                    } else {
                        resp_client.cmd = -1;
                    }
                }
                send(netfd, &resp_client, sizeof(resp_client), MSG_NOSIGNAL);
                break;
            default:
                // 未知命令
                bzero(sendBuf, sizeof(sendBuf));
                strcpy(sendBuf, "[ERROR]:unknown command");
                send(netfd, sendBuf, strlen(sendBuf), MSG_NOSIGNAL);
                break;
            }

            if(own_conn && conn){
                freeConn(pthreadPool->mysql_pool, conn);
                conn = NULL;
            }
        }    
    }
}

int makeWorker(threadPool_t *pthreadPool){
    for(int i = 0; i < pthreadPool->tidArr.workerNum;i++){
        int ret = pthread_create(&pthreadPool->tidArr.arr[i],NULL,threadFunc,pthreadPool);
        ERROR_CHECK(ret,-1,"pthread_create");
        printf("create pthread ok\n");
    }
    return 0;
}
